var express = require('express');
var router = express.Router();
let jwt = require('jsonwebtoken');
let { userModel, houseModel, codeModel } = require('../model/model');
const tencentCloud = require('tencentcloud-sdk-nodejs-iai');
const tencentcloudSms = require('tencentcloud-sdk-nodejs-sms');
const nodeMail = require('./sendEmail'); //引入发送邮件模块
const axios = require('axios');
/**
 * 声明AccessToken、RefreshToken的密钥
 */
const ACCESS_TOKEN_EXPIRATION = 10; //访问令牌有效期
const REFRESH_TOKEN_EXPIRATION = '1d'; //刷新令牌有效期
const SECRET_KEY = 'LIXIANGYU';
const refreshTokenMap = new Map();
// 配置微博登录信息
const WEIBO_USER_INFO_MAP = new Map();
const WEIBO_CLIENT_ID = '577138391'; // 微博 App Key
const WEIBO_CLIENT_SECRET = '35793d1212402c6346955cb557d77924'; // 微博 App Secret
const WEIBO_REDIRECT_URI = 'http://192.168.1.27:3000/login/auth/weibo/callback'; // 与微博开放平台配置的回调 URL 一致

// 生成函数令牌
function generateToken(name, expiration) {
  return jwt.sign({ name }, SECRET_KEY, { expiresIn: expiration });
}
// 封装生成短token和长token
function getToken(name) {
  let accessToken = generateToken(name, ACCESS_TOKEN_EXPIRATION); //短Token
  let refreshToken = generateToken(name, REFRESH_TOKEN_EXPIRATION); //长Token
  const refreshTokens = refreshTokenMap.get(name) || [];
  refreshTokens.push(refreshToken);
  refreshTokenMap.set(name, refreshTokens);
  return {
    accessToken,
    refreshToken,
  };
}

//=================================>账号密码登录
router.post('/userLogin', async (req, res) => {
  let info = await userModel.findOne({ ...req.body });
  if (info) {
    let { accessToken, refreshToken } = getToken(info.name);
    res.status(200).send({
      data: info,
      accessToken,
      refreshToken,
      message: '登录成功',
      code: 200,
    });
  } else {
    let judgePass = await userModel.findOne({ password: req.body.password });
    if (judgePass) {
      res.status(200).send({ message: '账号错误' });
    } else {
      res.status(200).send({ message: '密码错误' });
    }
  }
});

// 刷新短token
router.get('/refresh', async (req, res) => {
  const refreshToken = req.headers.refreshtoken;
  if (!refreshToken) {
    res.status(403).send('Forbidden');
  }
  try {
    const { name } = jwt.verify(refreshToken, SECRET_KEY);
    const accessToken = generateToken(name, ACCESS_TOKEN_EXPIRATION);
    res.status(200).send({ accessToken });
  } catch (error) {
    console.log('长token已过期');
    res.status(403).send('Forbidden');
  }
});

//人脸识别
router.post('/faceLogin', async (req, res) => {
  //获取前端传来的base64
  let b64 = req.body.b64;
  const IaiClient = tencentCloud.iai.v20200303.Client;
  try {
    const clientConfig = {
      credential: {
        //自己的腾讯secretId
        secretId: 'AKIDkfYGapqcN5B3mMlvpUw8AxVnqeDbuIfo',
        //自己的腾讯密匙
        secretKey: '3rUxCPl292lNk5PbsuiLDxTt68xa0Qhm',
      },
      region: 'ap-beijing', //地域参数（华北地区北京）
      profile: {
        httpProfile: {
          endpoint: 'iai.tencentcloudapi.com',
        },
      },
    };
    const client = new IaiClient(clientConfig);
    const params = {
      GroupIds: [
        //你创建的人员库ID
        'lixiangyu',
      ],
      Image: b64, //图片的base64格式编码
      NeedPersonInfo: 1, //是否返回人员具体信息。0 为关闭，1 为开启。默认为 0。
      QualityControl: 0, //图片质量控制。 0: 不进行控制； 1:较低的质量要求
      FaceMatchThreshold: 85, //人脸对比度设置为大于85才可
    };
    // console.log(params, 'params');
    let doc = await client.SearchFaces(params);

    // doc为人脸识别后的返回信息
    if (doc.Results[0].Candidates.length != 0) {
      //表示当前人脸库有该人员
      let personName = doc.Results[0].Candidates[0].PersonName; //拿到该人员的名称
      let data = await userModel.findOne({ name: personName });
      // console.log(data);
      if (data) {
        let { accessToken, refreshToken } = getToken(data.name);
        res.status(200).send({
          code: 200,
          message: personName,
          data,
          accessToken,
          refreshToken,
        });
      } else {
        res.status(200).send({ code: 401, message: '用户库里无此人' });
      }
    } else {
      res.status(200).send({
        code: 401,
        message: '人脸库无此人！',
      });
      return false;
    }
  } catch (err) {
    console.log(err);
  }
});

// 人脸录入
router.post('/addFace', async (req, res) => {
  //获取前端传来的base64
  let { img, PersonName, PersonId } = req.body;
  // console.log(req.body);
  const IaiClient = tencentCloud.iai.v20200303.Client;
  try {
    const clientConfig = {
      credential: {
        //自己的腾讯secretId
        secretId: 'AKIDkfYGapqcN5B3mMlvpUw8AxVnqeDbuIfo',
        //自己的腾讯密匙
        secretKey: '3rUxCPl292lNk5PbsuiLDxTt68xa0Qhm',
      },
      region: 'ap-beijing',
      profile: {
        httpProfile: {
          endpoint: 'iai.tencentcloudapi.com',
        },
      },
    };

    // 实例化要请求产品的client对象,clientProfile是可选的
    const client = new IaiClient(clientConfig);
    const params = {
      GroupId: 'lixiangyu',
      Gender: 1,
      PersonName: PersonName,
      PersonId: PersonId,
      Image: img,
      UniquePersonControl: 4,
      QualityControl: 0,
      NeedRotateDetection: 0,
    };
    client.CreatePerson(params).then(
      async (data) => {
        // await userModel.updateOne({ _id: PersonId }, { $set: { facestate: true } })
        // let userone = await userModel.find({ _id: PersonId })
        if (data.SimilarPersonId) {
          res.status(200).send({ code: 401, message: '您已经录入其他账号了' });
          return false;
        }
        res.status(200).send({ code: 200, message: '录入成功' });
      },
      (err) => {
        res.status(200).send({ code: 401, message: '该账号已经录入过人脸了' });
      }
    );
  } catch (err) {
    console.log(err);
  }
});

// 手机号注册验证码
router.post('/sms', async function (req, res, next) {
  var temp = Math.floor(100000 + Math.random() * 900000); //六位数字
  let { phone, name } = req.body;
  let phoneUser = await userModel.findOne({ phone });
  if (phoneUser) {
    res.status(200).send({ code: 401, message: '该手机号已经注册过了' });
    return false;
  }
  let nameUser = await userModel.findOne({ name });
  if (nameUser) {
    res.status(200).send({ code: 401, message: '该用户名已经存在了' });
    return false;
  }
  let codeInfo = await codeModel.find({ phone }).sort({ _id: 1 });
  if (
    codeInfo.length == 3 &&
    new Date(codeInfo[0].time).getTime() + 600000 > new Date().getTime()
  ) {
    return res
      .status(200)
      .send({ code: 401, message: '发送验证码过于频繁，请稍后再试' });
  }
  // Depends on tencentcloud-sdk-nodejs version 4.0.3 or higher

  const SmsClient = tencentcloudSms.sms.v20210111.Client;

  // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
  // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
  // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
  const clientConfig = {
    credential: {
      // 密钥id
      secretId: 'AKIDUJJLdfyPyCjR7Sn8d7pGgDsaK6xt4y9S',
      //自己的腾讯密匙
      secretKey: 'b0SIOmO7qaPHKTsUJJPiPLhGAGTl7UqC',
    },
    region: 'ap-beijing',
    profile: {
      httpProfile: {
        endpoint: 'sms.tencentcloudapi.com',
      },
    },
  };

  // 实例化要请求产品的client对象,clientProfile是可选的
  const client = new SmsClient(clientConfig);
  const params = {
    PhoneNumberSet: ['+86' + phone],
    SmsSdkAppId: '1400924361',
    SignName: '玩故记公众号',
    TemplateId: '2213773',
    TemplateParamSet: [temp.toString(), '5'],
  };
  client.SendSms(params).then(
    async (data) => {
      let obj = { phone: phone, code: temp };
      if (codeInfo.length == 3) {
        await codeModel.deleteOne({ phone });
      }
      codeModel.create(obj);
      res.send({
        code: 200,
        message: '验证码发送成功',
        codeNum: temp.toString(),
      });
    },
    (err) => {
      console.error('error', err);
    }
  );
});

// 邮箱注册验证码
router.post('/sendMail', async (req, res) => {
  let { email, name } = req.body;
  let phoneUser = await userModel.findOne({ email });
  if (phoneUser) {
    res.status(200).send({ code: 401, message: '该邮箱已经注册过了' });
    return false;
  }
  let nameUser = await userModel.findOne({ name });
  if (nameUser) {
    res.status(200).send({ code: 401, message: '该用户名已经存在了' });
    return false;
  }
  let codeInfo = await codeModel.find({ email }).sort({ _id: 1 });
  if (
    codeInfo.length == 3 &&
    new Date(codeInfo[0].time).getTime() + 600000 > new Date().getTime()
  ) {
    return res
      .status(200)
      .send({ code: 401, message: '发送验证码过于频繁，请稍后再试' });
  }
  const code = Math.floor(100000 + Math.random() * 900000); //生成6位随机验证码
  //发送邮件
  const mail = {
    from: `"理想寓APP"<2221967196@qq.com>`, // 发件人
    subject: '验证码', //邮箱主题
    to: email, //收件人，这里由post请求传递过来
    // 邮件内容，用html格式编写
    html: `
            <p>您好！</p>
            <p>您的验证码是：<strong style="color:red;">${code}</strong></p>
            <p>如果不是您本人操作，请无视此邮件</p>
        `,
  };
  await nodeMail.sendMail(mail, async (err, info) => {
    if (!err) {
      let obj = { email: email, code: code.toString() };
      if (codeInfo.length == 3) {
        await codeModel.deleteOne({ email });
      }
      codeModel.create(obj);
      res.status(200).send({
        code: 200,
        message: '验证码发送成功',
        codeNum: code.toString(),
      });
    } else {
      // console.log(err);
      res
        .status(200)
        .send({ code: 401, message: '验证码发送失败，请稍后重试' });
    }
  });
});

// 判断验证码的有效性进行注册
router.post('/addUser', async (req, res) => {
  let obj = req.body;
  let codeNum = obj.codeNum;
  delete obj.codeNum;
  let findObj = obj.email
    ? { email: obj.email, code: codeNum }
    : { phone: obj.phone, code: codeNum };
  let user = await codeModel.findOne(findObj);
  if (user) {
    await userModel.create(obj);
    res.status(200).send({ code: 200, message: '注册成功' });
  } else {
    res.status(200).send({ code: 401, message: '验证码错误' });
  }
});

// 忘记密码操作发送验证码
router.post('/forgetPassword', async (req, res) => {
  let { email, phone } = req.body;
  let findObj = email ? { email } : { phone };
  let user = await userModel.findOne(findObj);
  const code = Math.floor(100000 + Math.random() * 900000); //生成6位随机验证码
  if (user) {
    let codeInfo = await codeModel.find(findObj).sort({ _id: 1 });
    if (
      codeInfo.length == 3 &&
      new Date(codeInfo[0].time).getTime() + 600000 > new Date().getTime()
    ) {
      return res
        .status(200)
        .send({ code: 401, message: '发送验证码过于频繁，请稍后再试' });
    }
    if (email) {
      //发送邮件
      const mail = {
        from: `"理想寓APP"<2221967196@qq.com>`, // 发件人
        subject: '验证码', //邮箱主题
        to: email, //收件人，这里由post请求传递过来
        // 邮件内容，用html格式编写
        html: `
            <p>您好！</p>
            <p>您的验证码是：<strong style="color:red;">${code}</strong></p>
            <p>如果不是您本人操作，请无视此邮件</p>
        `,
      };
      await nodeMail.sendMail(mail, async (err, info) => {
        if (!err) {
          let obj = { email: email, code: code.toString() };
          if (codeInfo.length == 3) {
            await codeModel.deleteOne({ email });
          }
          codeModel.create(obj);
          res.status(200).send({
            code: 200,
            message: '验证码发送成功',
            codeNum: code.toString(),
          });
        } else {
          // console.log(err);
          res
            .status(200)
            .send({ code: 401, message: '验证码发送失败，请稍后重试' });
        }
      });
    }
    if (phone) {
      const SmsClient = tencentcloudSms.sms.v20210111.Client;
      // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
      // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
      // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
      const clientConfig = {
        credential: {
          // 密钥id
          secretId: 'AKIDUJJLdfyPyCjR7Sn8d7pGgDsaK6xt4y9S',
          //自己的腾讯密匙
          secretKey: 'b0SIOmO7qaPHKTsUJJPiPLhGAGTl7UqC',
        },
        region: 'ap-beijing',
        profile: {
          httpProfile: {
            endpoint: 'sms.tencentcloudapi.com',
          },
        },
      };

      // 实例化要请求产品的client对象,clientProfile是可选的
      const client = new SmsClient(clientConfig);
      const params = {
        PhoneNumberSet: ['+86' + phone],
        SmsSdkAppId: '1400924361',
        SignName: '玩故记公众号',
        TemplateId: '2213773',
        TemplateParamSet: [code.toString(), '5'],
      };
      client.SendSms(params).then(
        async (data) => {
          let obj = { phone: phone, code: code.toString() };
          if (codeInfo.length == 3) {
            await codeModel.deleteOne({ phone });
          }
          codeModel.create(obj);
          res.send({
            code: 200,
            message: '验证码发送成功',
            codeNum: code.toString(),
          });
        },
        (err) => {
          console.error('error', err);
        }
      );
    }
  } else {
    if (email) {
      res.status(200).send({ code: 401, message: '该邮箱未注册' });
    }
    if (phone) {
      res.status(200).send({ code: 401, message: '该手机号未注册' });
    }
  }
});

// 手机号/邮箱登录
router.post('/otherLogin', async (req, res) => {
  let { phone, email } = req.body;
  let findObj = phone ? { phone } : { email };
  let user = await userModel.findOne(findObj);
  if (user) {
    let { accessToken, refreshToken } = getToken(user.name);
    res.status(200).send({
      code: 200,
      message: '登录成功',
      data: user,
      accessToken,
      refreshToken,
    });
  } else {
    if (phone) {
      res
        .status(200)
        .send({ code: 401, message: '该手机号未注册/或手机号错误' });
    } else {
      res.status(200).send({ code: 401, message: '该邮箱未注册/或邮箱错误' });
    }
  }
});

// 找回密码
router.put('/resetPassword', async (req, res) => {
  let { email, phone, password } = req.body;
  let findObj = email ? { email } : { phone };
  try {
    await userModel.updateOne(findObj, { password: password });
    res.status(200).send({ code: 200, message: '重置密码成功' });
  } catch (error) {
    res.status(200).send({ code: 401, message: '重置密码失败' });
  }
});

// 微博
router.get('/auth/weibo/callback', async (req, res) => {
  const { code } = req.query;

  if (!code) {
    return res.status(400).send('No authorization code provided');
  }
  if (WEIBO_USER_INFO_MAP.has(code)) {
    let info = WEIBO_USER_INFO_MAP.get(code);
    const user = await userModel.findOne({ weiBoId: info.weiBoId });
    if (user) {
      const { accessToken, refreshToken } = getToken(user.name);
      return res.status(200).send({
        code: 200,
        message: '登录成功',
        data: user,
        accessToken,
        refreshToken,
      });
    } else {
      await userModel.create(info);
      let newUser = await userModel.findOne({ weiBoId: info.weiBoId });
      const { accessToken, refreshToken } = getToken(newUser.name);
      return res.status(200).send({
        code: 200,
        message: '登录成功',
        data: newUser,
        accessToken,
        refreshToken,
      });
    }
  } else {
    try {
      // 请求微博服务器，获取 access_token
      const tokenResponse = await axios.post(
        'https://api.weibo.com/oauth2/access_token',
        null,
        {
          params: {
            client_id: WEIBO_CLIENT_ID,
            client_secret: WEIBO_CLIENT_SECRET,
            grant_type: 'authorization_code',
            redirect_uri: WEIBO_REDIRECT_URI,
            code: code,
          },
        }
      );

      const { access_token, uid } = tokenResponse.data;

      // 用 access_token 获取用户信息
      const userInfoResponse = await axios.get(
        `https://api.weibo.com/2/users/show.json`,
        {
          params: {
            access_token,
            uid,
          },
        }
      );

      const userInfo = userInfoResponse.data;

      // 返回用户信息给前端
      // res.json({
      //     access_token,
      //     userInfo
      // });
      // 将获取的数据保存在new Map数据类型中
      let obj = {
        weiBoId: userInfo.idstr,
        name: userInfo.name,
        address: userInfo.location,
        gender: userInfo.gender == 'm' ? '男' : '女',
      };
      WEIBO_USER_INFO_MAP.set(code, obj);
    } catch (error) {
      console.error('Error fetching access token or user info:');
      res.status(500).send('Failed to authenticate with Weibo');
    }
  }
});

module.exports = router;
